import { SpriteFrame, _decorator, Camera, clamp, Collider, Color, Component, director, dynamicAtlasManager, EventTouch, geometry, Input, input, instantiate, Layers, macro, MeshRenderer, Node, NodePool, PhysicsSystem, Prefab, profiler, Quat, randomRangeInt, RigidBody, SpriteAtlas, toDegree, toRadian, Tween, tween, UIOpacity, UITransform, Vec3, view } from 'cc';
import { CubeMesh } from './Mesh';
import { EVENT_TYPE, Levels, MISSION_TYPE } from './Levels';
import Util from '../Script/Util';
import *as cc from "cc";
import DatasSpace from '../Script/Tool/DatasSpace';
import { MainGameUI } from '../Script/MainGameUI';
import { AdComponent } from '../Script/AdComponent';
import { AudioMgr, ENUM_CLIP } from '../Script/Tool/AudioMgr';
import EventMgr from '../Script/Tool/EventMgr';
import SkdComm from '../Script/SkdComm';
import { Rankl } from '../Script/Home/Rankl';
import { propTip } from '../Script/Tips/propTip';
import { GamePause } from '../Script/MainGame/GamePause';
import { AddTimePop } from '../Script/MainGame/AddTimePop';
const { ccclass, property } = _decorator;

//device.getFormatFeatures(FormData.RGBA32F)

@ccclass('Cubes')
export class Cubes extends Component {

  @property(Prefab)
  cube: Prefab = null;
  @property(Color)
  color: Color = new Color('#0785FA'); // ['#0785FA','#24B300','#FF7EEF','#FFFFFF'];
  @property(SpriteAtlas)
  sprAtlas: SpriteAtlas = null;
  @property(Node)
  cameraNode: Node = null;
  @property(Node)
  selcetNode: Node = null;
  @property(Node)
  uiNode: Node = null;
  @property({ type: Node })
  Bg: Node = null;

  @property({ type: [SpriteFrame] })
  sprites: cc.SpriteFrame[] = [];


  @property(cc.Node)
  sclectNode: cc.Node = null;

  @property(cc.Node)
  propTip:cc.Node=null;

  @property(cc.Label)
  cubeNum:cc.Label=null;
  @property(cc.Node)
  figerTip:cc.Node=null;


  camera0: Camera = null;
  camera1: Camera = null;

  private _level: number = 0;
  private _config: any = null;
  private _locked: boolean = false;

  private _verFOV: number = 45;
  private _baseNode: Node = null;
  private _nodePool: NodePool = new NodePool();
  private _localBuffer: Float32Array = new Float32Array(4);


  private _effectInc: number = 0;
  private _matchCount: number = 0;
  private _paiSelectCount: number = 0; //已选择总数
  private _paiRands: Array<string> = new Array(); //新随机队列
  private _paiSelets: Array<Array<Node>> = new Array();  //已选麻将
  private _paiInWorld: Map<string, Array<Node>> = new Map(); //未选麻将

  static inst: Cubes = null;
  private isGameOver: boolean = false;

  ///////////////////////////////////////////////////////////////////////////
  //测试按钮
  btnStart() {
    //显示词
    this.showWord();
    if (this._locked) return;
    this.resetGame();
    this.loadLevel(this._level);
    this.faPai();
    DatasSpace.Instance.ShareCount = 1;
    EventMgr.emit(EVENT_TYPE.EVENT_UPD_GAMEINFO)
    this.isGameOver = false;
    EventMgr.emit(EVENT_TYPE.EVENT_UPD_PROP_HEPAI, this.checkHePai());


    // console.log('开始加载');
  }

  /**洗牌按钮 */
  btnXiPai() {
    AudioMgr.Instance.play(ENUM_CLIP.Click);

    if (DatasSpace.Instance.propNumArr[0] < 1) {
      console.log('道具数量不足');
      this.propTip.getComponent(propTip).open(0);
      // AdComponent.Instance.loadVideoAd(0, (res) => {
      //   if (res) {
      //     this.xiPai();
      //   }
      // });

      return;
    } else {
      DatasSpace.Instance.propNumArr[0] -= 1;
      DatasSpace.Instance.setPropNum();
      MainGameUI.inst.initMainGameProp();

      if (this._locked) return;
      this.xiPai();
    }

    // DatasSpace.Instance.propNumArr[0] -= 1;
    // DatasSpace.Instance.setPropNum();
    // MainGameUI.inst.initMainGameProp();

    // if(this._locked) return;
    // this.xiPai();
  }

  /**翻牌按钮 */
  btnFanPai() {
    AudioMgr.Instance.play(ENUM_CLIP.Click);

    if (DatasSpace.Instance.propNumArr[1] < 1) {
      console.log('道具数量不足');
      this.propTip.getComponent(propTip).open(1);
      // AdComponent.Instance.loadVideoAd(0, (res) => {
      //   if (res) {
      //     this.fanPai();
      //   }
      // });
      return;
    } else {
      DatasSpace.Instance.propNumArr[1] -= 1;
      DatasSpace.Instance.setPropNum();
      MainGameUI.inst.initMainGameProp();

      if (this._locked) return;
      this.fanPai();
    }

    // DatasSpace.Instance.propNumArr[1] -= 1;
    // DatasSpace.Instance.setPropNum();
    // MainGameUI.inst.initMainGameProp();


    // if(this._locked) return;
    // this.fanPai();
  }

  /**消除按钮 */
  btnHePai() {
    if (this._locked) return;
    AudioMgr.Instance.play(ENUM_CLIP.Click);

    if (DatasSpace.Instance.propNumArr[2] < 1) {
      console.log('道具数量不足');
      this.propTip.getComponent(propTip).open(2);
      // if (DatasSpace.Instance.ShareCount > 0) {
      //   SkdComm.Instance.shareTo(
      //     () => {
      //       DatasSpace.Instance.ShareCount = 0;
      //       EventMgr.emit(EVENT_TYPE.EVENT_UPD_SHARE);
      //       MainGameUI.inst.initMainGameProp();
      //       this.hePai();
      //     }
      //   );
      // } else {
      //   AdComponent.Instance.loadVideoAd(0, (res) => {
      //     if (res) {
      //       this.hePai();
      //     }
      //   });
      // }
      return;
    } else {
      DatasSpace.Instance.propNumArr[2] -= 1;
      DatasSpace.Instance.setPropNum();
      MainGameUI.inst.initMainGameProp();

      if (this._locked) return;
      this.hePai();
    }

    // DatasSpace.Instance.propNumArr[2] -= 1;
    // DatasSpace.Instance.setPropNum();
    // MainGameUI.inst.initMainGameProp();

    // if(this._locked) return;
    // this.hePai();
  }

  /**撤回按钮 */
  btnTuiPai() {
    AudioMgr.Instance.play(ENUM_CLIP.Click);

    if (DatasSpace.Instance.propNumArr[3] < 1) {
      this.propTip.getComponent(propTip).open(3);
      // console.log('道具数量不足');
      // AdComponent.Instance.loadVideoAd(0, (res) => {
      //   if (res) {
      //     this.tuiPai();
      //   }
      // });
      return;
    } else {
      DatasSpace.Instance.propNumArr[3] -= 1;
      DatasSpace.Instance.setPropNum();
      MainGameUI.inst.initMainGameProp();
      if (this._locked) return;
      //this.tuiPai();
      Cubes.inst.reLiveGame();
    }

    // DatasSpace.Instance.propNumArr[3] -= 1;
    // DatasSpace.Instance.setPropNum();
    // MainGameUI.inst.initMainGameProp();

    // if(this._locked) return;
    // this.tuiPai();
  }

  // btnZhuoPai(){
  //   this.zhuaPai();
  // }


  ///////////////////////////////////////////////////////////////////////////

  putNode(node: Node) {
    this._nodePool.put(node);
  }

  getNode(): Node {
    let node = this._nodePool.get();
    if (!node) {
      node = instantiate(this.prefabNode());
    }
    return node;
  }

  prefabNode() {
    if (!this._baseNode) {
      this._baseNode = instantiate(this.cube);
      let render = this._baseNode.getComponent(MeshRenderer);

      render.mesh = CubeMesh;
      let texture = this.sprAtlas.getTexture();
      let material = render.getSharedMaterial(0);
      material.setProperty("mainTexture", texture);
      material.setProperty('mainColor', this.color);

    }
    return this._baseNode;
  }


  //垂直fov 转 水平fov
  verticalFOVToHorizontal(verFOV: number, aspect: number) {
    // 垂直fov的弧度
    let verFovRadian = toRadian(verFOV);
    // 视野高度的一半
    let camHalfHeight = Math.tan(verFovRadian / 2);
    // 水平视野的弧度
    let horFOVRadian = Math.atan(camHalfHeight * aspect) * 2;
    // 水平视野的角度
    return toDegree(horFOVRadian);
  }

  //水平fov 转 垂直fov 
  horizontalFOVToVertical(horFOV: number, aspect: number) {
    // 水平fov的弧度
    let horFOVRadian = toRadian(horFOV);
    // 视野宽度的一半
    let camHalfWidth = Math.tan(horFOVRadian / 2);
    // 垂直视野的弧度
    let verFOVRadian = Math.atan(camHalfWidth / aspect) * 2;
    // 垂直视野的角度
    return toDegree(verFOVRadian);
  }

  fixCamera() {

    this._verFOV = 45;
    let size = view.getVisibleSize();
    let aspect = size.width * 1.0 / size.height;

    //相机默认使用水平FOV，长宽>1：2 进行FOV适配转换
    this.camera0 = this.cameraNode.getChildByName('Camera0').getComponent(Camera);
    this.camera1 = this.cameraNode.getChildByName('Camera1').getComponent(Camera);

    if (aspect > 0.5) {
      //宽屏，长宽>1：2 进行适配转换
      let horFOVRadian = this.verticalFOVToHorizontal(this._verFOV, aspect);
      this.camera1.fov = this.camera0.fov = horFOVRadian;
    } else {
      //默认情况计算对应的verFOV
      this._verFOV = this.horizontalFOVToVertical(this._verFOV * 0.5, aspect);
    }

    this.camera0.camera.update(true);
    this.camera1.camera.update(true);
  }

  fixSceneUI() {

    let uiTop = this.uiNode.getChildByName('top');
    let uiBottom = this.uiNode.getChildByName('bottom');
    let uiSelect = this.uiNode.getChildByName('select');

    //3d场景宽度
    let worldLeft = this.camera0.convertToUINode(new Vec3(12, 0, 0), this.uiNode);

    //修正底部宽度
    let uitrans = uiBottom.getComponent(UITransform);
    uitrans.width = worldLeft.x * 2.1; //外扩大一点

    //修正顶部宽度
    uitrans = uiTop.getComponent(UITransform);
    uitrans.width = worldLeft.x * 2.1; //外扩大一点

    //修正Select的大小
    uitrans = uiSelect.getComponent(UITransform);
    let scale = worldLeft.x * 2 / uitrans.width;
    uiSelect.scale = new Vec3(scale, scale, scale);


    //调整3D背景大小
    let bg = this.cameraNode.getChildByName('BackGround');
    // let bg = this.Bg;
    let length = this.camera0.node.position.length();
    scale = 2 * Math.tan(toRadian(this._verFOV / 2));
    bg.scale.set(scale * length, scale * length, 1);

    //调整3D底面板位置
    let size = view.getVisibleSize();
    scale = -uiSelect.position.y / size.height;
    let offset = this.camera0.node.parent.position.z;
    this.selcetNode.setPosition(0, 0, scale * bg.scale.y + offset);

  }

  protected onLoad(): void {
    //AdComponent.Instance.showInterstitialFullShow();
    Cubes.inst = this;
    this.fixCamera();
    this.fixSceneUI();
    //profiler.showStats();
    input.on(Input.EventType.TOUCH_END, this.pickCube, this);


    if (Util.Instance.mainGameLevelMode == 1) {
      this.scheduleOnce(() => {
        // this._level = 0;
        if (DatasSpace.Instance.level < 4) {
          this._level = DatasSpace.Instance.level;
        } else if (DatasSpace.Instance.level >= 4) {
          this._level = 3;
        }
        this.btnStart();
      });
    } else if (Util.Instance.mainGameLevelMode == 2) {
      this._level = 3;
      this.startDailyChanllge();
    }


    cc.game.on('endGame', () => {
      this.gameOverByTimer();
    });

    cc.game.on('showWord', () => {
      this.showWord();
    });

    // cc.game.on('reLiveGame',()=>{
    //     this.reLiveGame();
    // });
    //开始计时
  }

  onDestroy() {

    this._nodePool.clear();
    this._baseNode && this._baseNode.destroy();
    input.off(Input.EventType.TOUCH_END, this.pickCube, this);
  }

  enablePhysics(node: Node, enable: boolean) {
    let body = node.getComponent(RigidBody);
    let collider = node.getComponent(Collider);
    body.enabled = enable;
    collider.enabled = enable;
  }

  setCubeTexture(node: Node, name: string) {


    let frame = this.sprAtlas.getSpriteFrame(name);
    // let frame = this.sprites.find(e=>e._name == name);

    let rect = frame.rect;
    let texture = frame.texture;
    let buffer = this._localBuffer;
    buffer[0] = rect.x * 1.0 / texture.width;
    buffer[1] = rect.y * 1.0 / texture.height;
    buffer[2] = rect.width * 1.0 / texture.width;
    buffer[3] = rect.height * 1.0 / texture.height;
    let mRender = node.getComponent(MeshRenderer);
    mRender.setInstancedAttribute('a_uv', buffer);

  }

  resetGame() {

    Tween.stopAll();
    this.unscheduleAllCallbacks();

    let effects = this.uiNode.getChildByName('effects');
    effects.children[0].active = false;
    effects.children[1].active = false;
    effects.children[2].active = false;

    this._paiSelets.forEach((nodes: Array<Node>) => {
      for (let i = nodes.length - 1; i >= 0; i--) {
        this.putNode(nodes[i]);
      }
    })

    let nodes = this.node.children;
    for (let i = nodes.length - 1; i >= 0; i--) {
      this.putNode(nodes[i]);
    }

    this._paiSelets.length = 0;
    this._paiSelectCount = 0;
    this._paiInWorld.clear();
    this._matchCount = 0;
    this._locked = false;

  }

  pickCube(event: EventTouch) {
    // 以下参数可选
    let ray = new geometry.Ray();
    this.camera0.screenPointToRay(event.getLocationX(), event.getLocationY(), ray);
    if (PhysicsSystem.instance.raycastClosest(ray, 0x2, 100, false)) {
      const raycastClosestResult = PhysicsSystem.instance.raycastClosestResult;
      let node = raycastClosestResult.collider.node;
      AudioMgr.Instance.play(ENUM_CLIP.CombineAndClick);
      if (this.flyToSelect(node)) {
        let nodes = this._paiInWorld.get(node.name);
        let idx = nodes.indexOf(node);
        if (idx >= 0)
          nodes.splice(idx, 1);
      }
    }

    EventMgr.emit(EVENT_TYPE.EVENT_UPD_PROP_HEPAI, this.checkHePai());

  }

  checkHePai() {
    let maxCount = 7 - this._paiSelectCount;
    if (maxCount <= 0) return true;

    let isAllow = false;
    let selects = this._paiSelets;
    for (let i = 0; i < selects.length; i++) {
      let nodes = selects[i];
      let length = 3 - nodes.length;
      if (length >= 0 && length <= maxCount) {
        let name = nodes[0].name;
        let wNodes = this._paiInWorld.get(name);
        if (wNodes && length <= wNodes.length) {
          for (let j = 0; j < length; j++) {
            if (this._paiSelectCount + 1 <= 7) {
              isAllow = true;
            }
          }
          break;
        }
      } else {
        isAllow = false;
      }
    }

    if (selects.length == 0) isAllow = true
    return isAllow;
  }

  loadLevel(lv) {
    // lv ++;
    let selectNames = [];
    this._config = { DampTime: 2 };
    if(lv==0){
      this.figerTip.active=true;
    }else{
      this.figerTip.active=false;
    }
    // if(lv === 1){
    //     let config = Levels[lv];
    //     let types = config.TypeRands;
    //     let times = config.Count;
    //     this._config = config;
    //     this._level = lv;

    //     let types = config.Types;
    //   for (let i = 0; i < types.length; i++) {
    //     selectNames[i] = types[i];
    //   }
    // }
    // lv = clamp(0, Levels.length - 1, lv);

    // let config = Levels[lv];

    // let types = config.TypeRands;
    // let times = config.Count;
    // this._config = config;
    // this._level = lv;

    //     //所有种类名字
    //     let selectNames = [];
    //     if (config.Types.length == 0) {
    //       let allPais = this.sprAtlas.spriteFrames;
    //       for (const key of Object.keys(allPais)) {
    //         selectNames.push(key);
    //       }
    //     } else {
    //       let types = config.Types;
    //       for (let i = 0; i < types.length; i++) {
    //         selectNames[i] = types[i];
    //       }
    //     }

    //     //随机剔除种类
    //     let length = selectNames.length;
    //     if (types > length) types = length;
    //     for (let i = 0; i < (length - types); i++) {
    //       let j = randomRangeInt(0, length--);
    //       selectNames.splice(j, 1);
    //     }

    //     //生成所有牌
    //     let paiRands = this._paiRands = [];
    //     for (let i = 0; i < times; i++) {
    //       let j = i % types;
    //       let name = selectNames[j];
    //       paiRands.push(name, name, name);
    //     }

    //     //随机打乱所有牌
    //     length = paiRands.length;
    //     for (let i = 0; i < length; i++) {
    //       let j = randomRangeInt(0, length);
    //       let temp = paiRands[i];
    //       paiRands[i] = paiRands[j];
    //       paiRands[j] = temp;
    //     }
    // console.error(paiRands);
    var t = lv;
    var n = this.config[Math.min(t, this.config.length - 1)]; //n 关卡数据
    // this.mahjongScale = n.Scale; //缩放
    var i = n.CombieCount;

    var o = null,
      r = [],
      a = [],
      s = 0;
    if (0 == n.RandomCount) s = Math.min(n.MJList.length, i), o = n.MJList;
    else {
      s = Math.min(Math.min(n.RandomCount,
        this.randomMjListA.length + this.randomMjListB.length), i),
        s = Math.min(s, 54),
        this.doRandomMjListA(),
        this.doRandomMjListB();
      for (var oo = [], l = Math.floor(Math.min(.7 * s, this.randomMjListA.length)),
        u = s - l, c = 0; c < l; c++) {
        oo.push(this.randomMjListA[c]);
      }

      for (var h = 0; h < u; h++) o.push(this.randomMjListB[h])
    }
    for (var p = 0; p < s; p++) r.push(o[p]);
    for (var d = i - s; 0 < d;) {
      for (var f = Math.min(d, o.length), m = 0; m < f; m++) a.push(o[m]);
      d -= f
    }
    var a = (a = a.concat(r)).sort(function (e, t) {
      return .5 < Math.random() ? -1 : 1
    }),
      g = [];
    if (80 < i) for (var b = 0; b < a.length; b++)
      g.push(a[b], a[b], a[b]);
    else for (var s = Math.floor(a.length / 2), y = 0; y < a.length; y++)
      y == s ? g.push(a[0], a[y], a[y]) : y < s ? g.push(a[y + 1], a[y], a[y])
        : g.push(a[y], a[y], a[y]);
    // this.shootMahjongs(n, g, e)
    // console.error(n, g);

    // var keys = Object.keys(this.sprAtlas.spriteFrames);
    //生成所有牌
    let paiRands = this._paiRands = g.map(e => e + "");
    // for (let i = 0; i < g.length; i++) {
    //   // let name = selectNames[j];
    //   // paiRands.push(keys[g[i]]);
    //   paiRands.push(g[i]);
    // }

    this._config.Count = paiRands.length / 3;
    // console.error(paiRands,this._config);
  }

  /*拿牌*/
  getPai(name: string | null = null) {
    if (!name) name = this._paiRands.pop();
    if (!name) return null;

    let node = this.getNode();
    this.node.addChild(node);

    this.enablePhysics(node, true);
    this.setCubeTexture(node, name);
    node.getComponent(RigidBody).angularDamping = 0.8;
    node.scale = this._level > 0 ? Vec3.ONE : new Vec3(1.25, 1.25, 1.25);;
    node.layer = Layers.Enum.DEFAULT;
    node.rotation = Quat.IDENTITY;
    node.name = name;

    //插入到world
    let nodes = this._paiInWorld.get(name);
    if (!nodes) {
      nodes = [];
      this._paiInWorld.set(name, nodes);
    }
    nodes.push(node);
    let childs=this.node.children;
    this.cubeNum.string="剩余："+childs.length;
    return node;

  }


  wakeUpOthers(node: Node) {
    let pos = node.position;
    let ray = new geometry.Ray(pos.x, pos.y, pos.z, 0, 1, 0);
    if (PhysicsSystem.instance.sweepBox(ray, new Vec3(1.5, 1, 2), node.rotation, 0x2, 20, false)) {
      let results = PhysicsSystem.instance.sweepCastResults;
      for (let i = 0; i < results.length; i++) {
        results[i].collider.attachedRigidBody.wakeUp();
      }
    }
  }

  combineEffect(position: Vec3) {

    AudioMgr.Instance.play(ENUM_CLIP.Combie);

    let parent = this.uiNode.getChildByName('effects');
    let out = this.camera0.convertToUINode(position, parent);
    let node = parent.children[this._effectInc];
    node.position = out;
    node.active = true;

    let n0 = node.children[0];
    let n1 = node.children[1];
    let n2 = node.children[2];
    let o1 = n1.getComponent(UIOpacity);
    let o2 = n2.getComponent(UIOpacity);
    n0.setScale(new Vec3(1.5, 1.5, 1.5));
    n1.setScale(new Vec3(0.5, 0.5, 0.5));
    n2.setScale(Vec3.ZERO);
    o1.opacity = 255;
    o2.opacity = 255;

    tween().target(n0).to(0.2, { scale: Vec3.ZERO }, { easing: "quadOut" }).start();

    tween().target(n1).to(0.1, { scale: Vec3.ONE }, { easing: "quintOut" }).start();
    tween().target(o1).to(0.1, { opacity: 0 }).start();

    tween().target(n2).to(0.2, { scale: Vec3.ONE }, { easing: "quintOut" }).start();
    tween().target(o2).delay(0.1).to(0.1, { opacity: 0 }).start();

    this.scheduleOnce(() => { node.active = false; }, 0.25);

    this._effectInc = (++this._effectInc) % parent.children.length;

  }


  fixPosition(count: number, idx: number, finish: Function) {
    if(this.figerTip.active){
      this.figerTip.active=false;
    }
    let selects = this._paiSelets;
    let pos = this.selcetNode.position;
    for (let i = 0, k = 0; i < selects.length; i++) {
      let nodes = selects[i];
      for (let j = 0; j < nodes.length; j++, k++) {
        let node = nodes[j];
        if (k >= idx) {
          tween().target(node).to(0.3, { position: new Vec3((k - 3) * 3.0-1.5, 0, pos.z) }, { easing: "quintOut" })
            .call(() => {
              if (--count == 0) {
                finish();

              }
            }).start();
        }
      }
    }
  }

  fixSelectEnd() {
    let count = 0;
    let selects = this._paiSelets;
    for (let i = selects.length - 1; i >= 0; i--) {
      let nodes = selects[i];
      let length = nodes.length;
      if (length >= 3) {
        count += 3;
        this._paiSelectCount -= 3;
        if (nodes.length == 3) selects.splice(i, 1);
        let n0 = nodes.pop();
        let n1 = nodes.pop();
        let n2 = nodes.pop();
        const end = () => {
          AudioMgr.Instance.playMj(n1.name);

          this.combineEffect(n1.worldPosition);
          this.putNode(n0);
          this.putNode(n1);
          this.putNode(n2);
          count -= 3;
          if (count == 0) {
            this.fixPosition(this._paiSelectCount, 0, () => { });
          }
          let childs=this.node.children;
          this.cubeNum.string="剩余："+childs.length;
          if (++this._matchCount == this._config.Count) {
            this._level++;
            // this.btnStart(); //游戏结束完成
            this.gamePass();
          }

        };
        let pos = n1.position;
        tween().target(n0).to(0.1, { position: pos }, { easing: "quadOut" }).start();
        tween().target(n2).to(0.1, { position: pos }, { easing: "quadOut" }).call(end).start();
      }
    }
  }

  /**游戏通关 闯关成功 */
  gamePass() {
    console.log('游戏通关');
    AudioMgr.Instance.play(ENUM_CLIP.Win)
    // this.btnStart();
    DatasSpace.Instance.addLongMission_Target(MISSION_TYPE.LEVEL, 1)
    DatasSpace.Instance.addMission_Target(MISSION_TYPE.LEVEL, 1)
    if (Util.Instance.mainGameLevelMode == 1) {
      Util.Instance.GloberLoadPrefab('LevelPass', 2, (res) => {
        let newNode = cc.instantiate(res);
        cc.find('UI').getChildByName('PopView').addChild(newNode);
        this.hideWord();
        newNode.setPosition(0, 0, 0);
        DatasSpace.Instance.piggyBankGlodNum += 25;
        DatasSpace.Instance.setPiggyBankNum();

        //首页宝箱
        DatasSpace.Instance.homeBox_levelPassCountNum += 1;
        DatasSpace.Instance.setHomeBoxLevelPassCount();

        DatasSpace.Instance.level += 1;
        DatasSpace.Instance.setPlayerLevel();
        Rankl.setRank(DatasSpace.Instance.level)
      }, () => {

      });
    } else if (Util.Instance.mainGameLevelMode == 2) {
      Util.Instance.GloberLoadPrefab('LevelPassChanllge', 2, (res) => {
        let newNode = cc.instantiate(res);
        cc.find('UI').getChildByName('PopView').addChild(newNode);
        this.hideWord();
        newNode.setPosition(0, 0, 0);
      }, () => {

      });
    }

  }
  /**本局失败次数*/
  loseTime:number=0;
  /**游戏结束 游戏失败 闯关失败*/
  gameOver() {
    if (this.isGameOver) {
      return;
    }
    AudioMgr.Instance.play(ENUM_CLIP.Fail)

    console.log('游戏结束');
    this.isGameOver = true;
    Util.Instance.GloberLoadPrefab('Lose', 2, (res) => {
      let newNode = cc.instantiate(res);
      cc.find('UI').getChildByName('PopView').addChild(newNode);
      newNode.setPosition(0, 0, 0);
      newNode.getComponent(GamePause).openLose(this.loseTime);
      this.loseTime++;
      this.hideWord();
    }, () => {

    });
  }


  shareTime2:number=0;
  /**
   * 游戏结束 游戏失败
   * time 2024 5 29 12:12
   */
  gameOverByTimer() {
    if (this.isGameOver) {
      return;
    }
    console.log('游戏结束');
    this.isGameOver = true;
    Util.Instance.GloberLoadPrefab('LoseByTimer', 2, (res) => {
      let newNode = cc.instantiate(res);
      cc.find('UI').getChildByName('PopView').addChild(newNode);
      newNode.setPosition(0, 0, 0);
      newNode.getComponent(AddTimePop).openLose(this.shareTime2);
      this.shareTime2++;
      this.hideWord();
    }, () => {

    });
  }
  maxPai:number=7;
  @property(Node)
  addBtn:Node=null;
  addMax(){
    AdComponent.Instance.loadVideoAd(77, (res) => {
      if (res) {
          this.maxPai=8;
          this.addBtn.active=false;
      }
    });
  }
  flyToSelect(node: Node) {
    console.log(node);
    if (this._paiSelectCount + 1 > this.maxPai) {
      return false;
    }
    this.enablePhysics(node, false);
    this.wakeUpOthers(node);
    this._paiSelectCount++;

    node.setParent(this.selcetNode.parent);
    node.layer = Layers.Enum.UI_3D;
    node.rotation = Quat.IDENTITY;
    node.setScale(new Vec3(0.95, 0.95, 0.95));

    let idx = 0;
    let isInsert = true;
    let selects = this._paiSelets;
    for (let i = 0, j = selects.length; i < j; i++) {
      let nodes = selects[i];
      let length = nodes.length;
      if (nodes[0].name == node.name) {
        isInsert = false;
        nodes.push(node);
        idx += length;
        break;
      }
      idx += length;
    }

    // 计算后移个数
    let count = this._paiSelectCount - idx;
    if (isInsert) selects.push([node]);
    this.fixPosition(count, idx, () => {
      this.fixSelectEnd();
      if (this._paiSelectCount >= this.maxPai) {
        this.gameOver();
      }
    });

    return true;
  }

  /*合牌，选取一对组合*/
  hePai() {

    //最大空位牌数
    let maxCount = 7 - this._paiSelectCount;
    if (maxCount <= 0) return false;

    let selects = this._paiSelets;
    for (let i = 0; i < selects.length; i++) {
      let nodes = selects[i];
      let length = 3 - nodes.length;
      if (length >= 0 && length <= maxCount) {
        let name = nodes[0].name;
        let wNodes = this._paiInWorld.get(name);
        if (wNodes && length <= wNodes.length) {
          for (let j = 0; j < length; j++) {
            this.flyToSelect(wNodes.pop());
          }
          break;
        }
      }
    }

    if (selects.length == 0) {
      console.log('牌区没有牌');
      let rangNodes = () => {
        const keys = Array.from(this._paiInWorld.keys());
        const randomIndex = randomRangeInt(0, this._paiInWorld.size)
        const randomKey = keys[randomIndex];
        let nodes = this._paiInWorld.get(randomKey);
        console.log(this._paiInWorld)
        if (nodes.length <= 0) {
          return rangNodes()
        } else {
          return { key: randomKey, value: nodes }
        }
      }

      let nodes = rangNodes()
      // console.log(this._paiInWorld, keys, randomKey, randomIndex, nodes)
      let value = nodes.value
      if (value.length < 3) return;
      for (let i = 0; i < 3; i++) {
        this.flyToSelect(value.pop());
      }
      if (value.length == 0) {
        this._paiInWorld.delete(nodes.key);
      }
    }

    DatasSpace.Instance.addMission_Target(MISSION_TYPE.USE_PROP_XIAOCHU, 1)
    return true;

  }

  /*翻牌，全部反面反转正面)*/
  fanPai() {
    DatasSpace.Instance.addMission_Target(MISSION_TYPE.USE_PROP_FANPAI, 1)

    this._locked = true;

    let side = 1;
    let ttt = tween(this.node);
    let node = this.camera0.node;
    for (let i = 0; i < 50; i++) {
      side = -1 * side;
      let x = (1.0 - Math.sin(i * Math.PI / 100.0)) * 3;
      ttt.then(tween(node).to(0.02, { position: new Vec3(x * side, 0, 0) }));
    }
    ttt.then(tween(node).to(0.02, { position: Vec3.ZERO }));

    this.scheduleOnce(() => {
      let childs = this.node.children;
      for (let i = 0; i < childs.length; i++) {
        let node = childs[i];
        node.rotation = Quat.IDENTITY;
        node.getComponent(RigidBody).angularDamping = 1.0;
      }
    });
    this._locked = false;
    // ttt.call(() => {
    //   let childs = this.node.children;
    //   for (let i = 0; i < childs.length; i++) {
    //     childs[i].getComponent(RigidBody).angularDamping = 0.8;
    //   }
    //   this._locked = false;
    // }).start();

  }

  /*洗牌，剩下回收再重发牌*/
  xiPai() {
    this._locked = true;

    let childs = this.node.children;
    let length = childs.length;
    if (length <= 0) return;

    PhysicsSystem.instance.enable = false;
    this._paiInWorld.clear();

    //回收场上牌
    let count = length;
    for (let i = 0; i < length; i++) {
      let node = childs[i];
      let pos = node.position;
      let time = pos.length() / 40.0;
      tween().target(node).to(time, { position: new Vec3(0, pos.y, 0) })
        .call(() => {
          this._paiRands.push(node.name);
          this.putNode(node);//回收

          if (--count <= 0) {
            this.faPai();
          }
        }).start();
    }

  }



  /*抓牌，磁铁吸若干个*/
  zhuaPai() {

    let count = 0;
    let times = 2;
    let selects = [];
    this._paiInWorld.forEach((nodes: Array<Node>) => {
      if (nodes.length >= 3) {
        if (count < 3 * times) {
          count += 3;
          selects.push(nodes.pop());
          selects.push(nodes.pop());
          selects.push(nodes.pop());
        }
      }
    });

    // childs.sort((a:Node,b:Node)=>b.position.y-a.position.y);

    //开始吸牌    
    for (let i = count - 1; i >= 0; i--) {
      let node = selects[i];
      this.enablePhysics(node, false);
      let time = node.position.length() / 20.0;
      tween().target(node).to(time, { position: new Vec3(0, 10, 0) }, { easing: "quartIn" })
        .call(() => {
          this.putNode(node);
          if (--count == 0) {
            //结束吸牌
          }
        }).start();
    }
  }

  /*退牌*/
  tuiPai() {
    DatasSpace.Instance.addMission_Target(MISSION_TYPE.USE_PROP_CHEHUI, 1)

    let end = this._paiSelets.length - 1;
    if (end >= 0) {
      let nodes = this._paiSelets[end];
      let node = nodes.pop();
      if (node) {
        this._paiSelectCount--;
        if (nodes.length == 0) this._paiSelets.pop();

        tween().target(node).to(0.2, { position: new Vec3((end - 3) * 3, 15, 0) }, { easing: "quartOut" })
          .call(() => {
            this.putNode(node);
            let n = this.getPai(node.name);
            let body = n.getComponent(RigidBody);
            body.setLinearVelocity(new Vec3(0, -2, 0));
            n.scale = this._level > 0 ? Vec3.ONE : new Vec3(1.25, 1.25, 1.25);
          }).start();

      }
    }

    EventMgr.emit(EVENT_TYPE.EVENT_UPD_PROP_HEPAI, this.checkHePai());

  }

  /* 发牌*/
  faPai() {

    this._locked = true;
    PhysicsSystem.instance.enable = true;

    //首次发牌
    if (this._level == 0) {
      for (let i = 0; true; i++) {
        let node = this.getPai();
        if (!node) break;
        console.log('开始发牌');
        // node.scale = new Vec3(1.25,1.25,1.25);
        node.position = new Vec3(((i % 3) - 1) * 8, 1, ((~~(i / 3)) - 1) * 10);
        node.rotation = Quat.fromAxisAngle(new Quat(), Vec3.UNIT_Y, Math.random() * Math.PI / 6);
      }
      this._locked = false;
      return;
    } else {
      AudioMgr.Instance.play(ENUM_CLIP.CreateMahjon, true);
    }



    let inc = 0;
    let step = 15;
    let angle = 0;
    let radius = 3;
    let velocity = 30;

    const animation = () => {
      let node = this.getPai();
      if (!node) {
        this.unschedule(animation);
        this._locked = false;
        //发牌结束
        console.log('发牌结束')
        AudioMgr.Instance.stop();
        return;
      }



      let x = Math.cos(angle);
      let z = Math.sin(angle);
      let y = 1.0 + (inc++ / 10.0) * 0.5;
      node.position = new Vec3(x * radius, y, z * radius);

      let body = node.getComponent(RigidBody);
      body.setLinearVelocity(new Vec3(x * velocity, 0, z * velocity));
      this.scheduleOnce(() => { body.angularDamping = 0.8; }, this._config.DampTime);
      body.angularDamping = 1;

      angle += step * Math.PI / 180.0;
    }

    this.schedule(animation, 0.03);



  }


  //======================================================5月28日增加=========================================================
  //增加时间  2024年 5月 28日  22:43
  hideWord() {
    cc.find('World').active = false;
  }

  //增加时间  2024年 5月 28日  22:44
  showWord() {
    cc.find('World').active = true;
    this.isGameOver = false;
    // this.reLiveGame();
  }

  //======================================================5月29日增加=========================================================
  /**
   * @fn 开始每日挑战模式
   * @time 2024 5 29 15:49
   */
  startDailyChanllge() {
    this.btnStart();
    this._level = 4;
  }

  /**
   * @fn 复活功能
   * @time 2024 5 30
   */
  reLiveGame() {
    if (this._locked) return;
    this.showWord();
    for (let i = 0; i < 7; i++) {
      this.tuiPai();
    }
    // this.tuiPai();
  }

  config = [{
    Level: 1,
    CombieCount: 3,
    RandomCount: 0,
    Time: 300,
    CreateTime: 3,
    Scale: 1.2,
    MJList: [11, 12, 13, 14, 15, 1, 2, 3, 4, 5, 21, 22, 23, 24, 25, 31, 35, 36, 37, 34],
    upScale: 1,
    initY: -5
  },
  {
    Level: 2,
    CombieCount: 35,
    RandomCount: 0,
    Time: 600,
    CreateTime: 3,
    Scale: 1,
    MJList: [14, 15, 16, 17, 18, 19, 1, 2, 3, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 4, 5, 6],
    upScale: .9,
    initY: -5
  },
  {
    Level: 3,
    CombieCount: 40,
    RandomCount: 0,
    Time: 720,
    CreateTime: 3,
    Scale: 1,
    MJList: [11, 12, 13, 14, 15, 16, 17, 41, 42, 43, 44, 45, 46, 47, 2, 3, 4, 5, 6, 7, 8, 35, 31, 34],
    upScale: .9,
    initY: -5
  },
  {
    Level: 4,
    CombieCount: 45,
    RandomCount: 0,
    Time: 600,
    CreateTime: 3,
    Scale: 1,
    MJList: [17, 18, 19, 1, 2, 3, 4, 5, 6, 7, 8, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 25, 26, 27, 28, 31],
    upScale: .9,
    initY: -5
  },
  {
    Level: 5,
    CombieCount: 50,
    RandomCount: 0,
    Time: 720,
    CreateTime: 3,
    Scale: 1,
    MJList: [11, 12, 21, 22, 23, 24, 25, 26, 27, 28, 29, 50, 32, 33, 35, 41, 42, 43, 44, 45, 46, 47, 48, 49, 15, 16, 17],
    upScale: .9,
    initY: -5
  },
  {
    Level: 6,
    CombieCount: 50,
    RandomCount: 0,
    Time: 600,
    CreateTime: 3,
    Scale: 1,
    MJList: [12, 15, 21, 22, 23, 24, 25, 27, 37, 41, 42, 43, 44, 35, 19, 45, 11, 31, 32, 34, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55],
    upScale: .9,
    initY: -5
  },
  {
    Level: 7,
    CombieCount: 50,
    RandomCount: 30,
    Time: 720,
    CreateTime: 3,
    Scale: 1,
    MJList: [],
    upScale: .9,
    initY: -5
  },
  {
    Level: 8,
    CombieCount: 55,
    RandomCount: 32,
    Time: 600,
    CreateTime: 3,
    Scale: .95,
    MJList: [],
    upScale: .9,
    initY: -5
  },
  {
    Level: 9,
    CombieCount: 55,
    RandomCount: 34,
    Time: 720,
    CreateTime: 3,
    Scale: .95,
    MJList: [],
    upScale: .9,
    initY: -5
  },
  {
    Level: 10,
    CombieCount: 60,
    RandomCount: 36,
    Time: 600,
    CreateTime: 3,
    Scale: .95,
    MJList: [],
    upScale: .9,
    initY: -5
  },
  {
    Level: 11,
    CombieCount: 60,
    RandomCount: 38,
    Time: 720,
    CreateTime: 3,
    Scale: .95,
    MJList: [],
    upScale: .9,
    initY: -5
  },
  {
    Level: 12,
    CombieCount: 65,
    RandomCount: 39,
    Time: 600,
    CreateTime: 3,
    Scale: .95,
    MJList: [],
    upScale: .9,
    initY: -5
  },
  {
    Level: 13,
    CombieCount: 65,
    RandomCount: 40,
    Time: 720,
    CreateTime: 3,
    Scale: .95,
    MJList: [],
    upScale: .9,
    initY: -5
  },
  {
    Level: 14,
    CombieCount: 70,
    RandomCount: 41,
    Time: 600,
    CreateTime: 3,
    Scale: .95,
    MJList: [],
    upScale: .9,
    initY: -5
  },
  {
    Level: 15,
    CombieCount: 70,
    RandomCount: 42,
    Time: 720,
    CreateTime: 3,
    Scale: .95,
    MJList: [],
    upScale: .9,
    initY: -5
  },
  {
    Level: 16,
    CombieCount: 75,
    RandomCount: 43,
    Time: 600,
    CreateTime: 3,
    Scale: .95,
    MJList: [],
    upScale: .9,
    initY: -5
  },
  {
    Level: 17,
    CombieCount: 75,
    RandomCount: 43,
    Time: 720,
    CreateTime: 3,
    Scale: .95,
    MJList: [],
    upScale: .9,
    initY: -5
  },
  {
    Level: 18,
    CombieCount: 80,
    RandomCount: 45,
    Time: 600,
    CreateTime: 3,
    Scale: .95,
    MJList: [],
    upScale: .9,
    initY: -5
  },
  {
    Level: 19,
    CombieCount: 80,
    RandomCount: 46,
    Time: 720,
    CreateTime: 3,
    Scale: .95,
    MJList: [],
    upScale: .9,
    initY: -5
  },
  {
    Level: 20,
    CombieCount: 85,
    RandomCount: 47,
    Time: 600,
    CreateTime: 3,
    Scale: .95,
    MJList: [],
    upScale: .9,
    initY: -5
  },
  {
    Level: 21,
    CombieCount: 85,
    RandomCount: 48,
    Time: 720,
    CreateTime: 3,
    Scale: .95,
    MJList: [],
    upScale: .9,
    initY: -5
  },
  {
    Level: 22,
    CombieCount: 90,
    RandomCount: 49,
    Time: 600,
    CreateTime: 3,
    Scale: .95,
    MJList: [],
    upScale: .9,
    initY: -5
  },
  {
    Level: 23,
    CombieCount: 90,
    RandomCount: 50,
    Time: 720,
    CreateTime: 3,
    Scale: .95,
    MJList: [],
    upScale: .9,
    initY: -5
  },
  {
    Level: 24,
    CombieCount: 95,
    RandomCount: 51,
    Time: 600,
    CreateTime: 3,
    Scale: .95,
    MJList: [],
    upScale: .9,
    initY: -5
  },
  {
    Level: 25,
    CombieCount: 95,
    RandomCount: 55,
    Time: 720,
    CreateTime: 3,
    Scale: .95,
    MJList: [],
    upScale: .9,
    initY: -5
  },
  {
    Level: 26,
    CombieCount: 100,
    RandomCount: 53,
    Time: 600,
    CreateTime: 3,
    Scale: .95,
    MJList: [],
    upScale: .9,
    initY: -5
  },
  {
    Level: 27,
    CombieCount: 100,
    RandomCount: 54,
    Time: 720,
    CreateTime: 3,
    Scale: .95,
    MJList: [],
    upScale: .9,
    initY: -5
  },
  {
    Level: 28,
    CombieCount: 100,
    RandomCount: 55,
    Time: 600,
    CreateTime: 3,
    Scale: .95,
    MJList: [],
    upScale: .9,
    initY: -5
  },
  {
    Level: 29,
    CombieCount: 100,
    RandomCount: 56,
    Time: 720,
    CreateTime: 3,
    Scale: .95,
    MJList: [],
    upScale: .9,
    initY: -5
  },
  {
    Level: 30,
    CombieCount: 100,
    RandomCount: 57,
    Time: 600,
    CreateTime: 3,
    Scale: .95,
    MJList: [],
    upScale: .9,
    initY: -5
  },
  {
    Level: 31,
    CombieCount: 100,
    RandomCount: 58,
    Time: 720,
    CreateTime: 3,
    Scale: .95,
    MJList: [],
    upScale: .9,
    initY: -5
  },
  {
    Level: 32,
    CombieCount: 100,
    RandomCount: 59,
    Time: 600,
    CreateTime: 3,
    Scale: .95,
    MJList: [],
    upScale: .9,
    initY: -5
  },
  {
    Level: 33,
    CombieCount: 100,
    RandomCount: 60,
    Time: 720,
    CreateTime: 3,
    Scale: .95,
    MJList: [],
    upScale: .9,
    initY: -5
  },
  {
    Level: 34,
    CombieCount: 100,
    RandomCount: 61,
    Time: 600,
    CreateTime: 3,
    Scale: .95,
    MJList: [],
    upScale: .9,
    initY: -5
  },
  {
    Level: 35,
    CombieCount: 100,
    RandomCount: 62,
    Time: 720,
    CreateTime: 3,
    Scale: .95,
    MJList: [],
    upScale: .9,
    initY: -5
  },
  {
    Level: 36,
    CombieCount: 100,
    RandomCount: 63,
    Time: 600,
    CreateTime: 3,
    Scale: .95,
    MJList: [],
    upScale: .9,
    initY: -5
  },
  {
    Level: 37,
    CombieCount: 100,
    RandomCount: 64,
    Time: 720,
    CreateTime: 3,
    Scale: .95,
    MJList: [],
    upScale: .9,
    initY: -5
  },
  {
    Level: 38,
    CombieCount: 100,
    RandomCount: 65,
    Time: 600,
    CreateTime: 3,
    Scale: .95,
    MJList: [],
    upScale: .9,
    initY: -5
  },
  {
    Level: 39,
    CombieCount: 100,
    RandomCount: 66,
    Time: 720,
    CreateTime: 3,
    Scale: .95,
    MJList: [],
    upScale: .9,
    initY: -5
  },
  {
    Level: 40,
    CombieCount: 100,
    RandomCount: 67,
    Time: 600,
    CreateTime: 3,
    Scale: .95,
    MJList: [],
    upScale: .9,
    initY: -5
  },
  {
    Level: 41,
    CombieCount: 100,
    RandomCount: 68,
    Time: 720,
    CreateTime: 3,
    Scale: .95,
    MJList: [],
    upScale: .9,
    initY: -5
  },
  {
    Level: 42,
    CombieCount: 100,
    RandomCount: 69,
    Time: 600,
    CreateTime: 3,
    Scale: .95,
    MJList: [],
    upScale: .9,
    initY: -5
  },
  {
    Level: 43,
    CombieCount: 100,
    RandomCount: 70,
    Time: 720,
    CreateTime: 3,
    Scale: .95,
    MJList: [],
    upScale: .9,
    initY: -5
  },
  {
    Level: 44,
    CombieCount: 100,
    RandomCount: 71,
    Time: 600,
    CreateTime: 3,
    Scale: .95,
    MJList: [],
    upScale: .9,
    initY: -5
  },
  {
    Level: 45,
    CombieCount: 100,
    RandomCount: 72,
    Time: 720,
    CreateTime: 3,
    Scale: .95,
    MJList: [],
    upScale: .9,
    initY: -5
  },
  {
    Level: 46,
    CombieCount: 100,
    RandomCount: 73,
    Time: 600,
    CreateTime: 3,
    Scale: .95,
    MJList: [],
    upScale: .9,
    initY: -5
  },
  {
    Level: 47,
    CombieCount: 100,
    RandomCount: 74,
    Time: 720,
    CreateTime: 3,
    Scale: .95,
    MJList: [],
    upScale: .9,
    initY: -5
  },
  {
    Level: 48,
    CombieCount: 100,
    RandomCount: 75,
    Time: 600,
    CreateTime: 3,
    Scale: .95,
    MJList: [],
    upScale: .9,
    initY: -5
  },
  {
    Level: 49,
    CombieCount: 100,
    RandomCount: 76,
    Time: 720,
    CreateTime: 3,
    Scale: .95,
    MJList: [],
    upScale: .9,
    initY: -5
  },
  {
    Level: 50,
    CombieCount: 100,
    RandomCount: 77,
    Time: 600,
    CreateTime: 3,
    Scale: .95,
    MJList: [],
    upScale: .9,
    initY: -5
  },
  {
    Level: 51,
    CombieCount: 100,
    RandomCount: 78,
    Time: 720,
    CreateTime: 3,
    Scale: .95,
    MJList: [],
    upScale: .9,
    initY: -5
  },
  {
    Level: 52,
    CombieCount: 100,
    RandomCount: 79,
    Time: 600,
    CreateTime: 3,
    Scale: .95,
    MJList: [],
    upScale: .9,
    initY: -5
  },
  {
    Level: 53,
    CombieCount: 100,
    RandomCount: 80,
    Time: 720,
    CreateTime: 3,
    Scale: .95,
    MJList: [],
    upScale: .9,
    initY: -5
  },
  {
    Level: 54,
    CombieCount: 100,
    RandomCount: 80,
    Time: 600,
    CreateTime: 3,
    Scale: .95,
    MJList: [],
    upScale: .9,
    initY: -5
  }];
  randomMjListA = [1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21, 22, 23, 24, 25, 26, 27, 28, 29, 31, 32, 33, 34, 35, 36, 37];
  randomMjListB = [41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84];
  doRandomMjListA() {
    return this.randomMjListA.sort(function (e, t) {
      return 0.5 < Math.random() ? -1 : 1
    })
  }
  doRandomMjListB() {
    return this.randomMjListB.sort(function (e, t) {
      return 0.5 < Math.random() ? -1 : 1
    })
  }
}


